IAM ポリシーの Conditions 句に aws:SourceIp と aws:VpcSourceIp を併記できるかを確認してみた。
はじめに
猫とアポロチョコが好きな、アノテーション株式会社の m.hayakawa です。
IAM ポリシーに IAM アドレス制限を掛けたい場合があります。パブリック IP アドレスとプライベート IP アドレスを両方使いたい場合があります。例えば、S3 へファイルを転送する際はインターネットを経由させずに、VPC エンドポイントを経由させたいときなどが考えられます。
IP アドレスに関する条件は Condition 句を使用しますが、パブリック IP アドレスを評価する場合は aws:SourceIp 条件コンテキストキー、プライベート IP アドレスを評価する場合は aws:VpcSourceIp 条件コンテキストキーを使用します。
これを併記することはできるか、本記事にて検証していきます。
前提条件
Amazon Linux 2023 の EC2 インスタンスをパブリックサブネット上に作成します。
IAM ロール: EC2RoleForTest を作成します。信頼関係に EC2 サービスを追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
}
}
]
}
AWS 管理ポリシー: AdministratorAccess をアタッチします。
上記の IAM ロールを EC2 にアタッチします。
EC2 のパブリック IP は 35.78.2.29 とします(こちらは検証時に使用しており、すでに削除済みです)。
検証
パブリック IP アドレスで制御できるか
始めに、デフォルトの状態で AWS CLI コマンドを実行できるかをチェックします。
$ aws s3 ls
2024-08-13 04:10:06 test-bucket-blog
問題なく実行できます。
では、次にすべてのアクションを Deny するインラインポリシーを IAM ロールにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllDeny",
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
当然、アクションは明示的に拒否されるので失敗します。
$ aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:sts::<AccountID>:assumed-role/EC2RoleForTest/i-01230123012301234 is not authorized to perform: s3:ListAllMyBuckets with an explicit deny in an identity-based policy
それでは、EC2 のパブリック IP: 35.78.2.29 を明示的な拒否から除外してみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyNotIpAddress",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"35.78.2.29/32"
]
}
}
}
]
}
AWS CLI コマンドが成功しました。
$ aws s3 ls
2024-08-13 04:10:06 test-bucket-blog
これにより、EC2 のパブリック IP を Condition 句に指定することで、特定の IP アドレスからのアクセスを可能にできることが分かります。
プライベート IP アドレスで制御できるか
プライベート IP で AWS 環境へアクセスするために、参考資料 [1] の記事を参考に VPC エンドポイントを作成していきます。
本記事では S3 インターフェースエンドポイントを用いて検証します。
S3 インターフェースエンドエンドポイント経由で明示的にアクセスする場合は、--endpoint-url オプションを使用します。
$ aws s3 ls --endpoint-url http://bucket.vpce-0123456789abcdef0-sample.s3.ap-northeast-1.vpce.amazonaws.com
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:sts::<AccountID>:assumed-role/EC2RoleForTest/i-01230123012301234 is not authorized to perform: s3:ListAllMyBuckets with an explicit deny in an identity-based policy
明示的な拒否で失敗していることが分かりました。
インターフェースエンドポイントは VPC の CIDR の範囲で IP アドレスが割り当てられるため、IAM ポリシーにその IP アドレスを許可するように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyNotIpAddress2",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"35.78.2.29/32"
],
"aws:VpcSourceIp": [
"172.31.0.0/16"
]
}
}
}
]
}
再度実行します。
$ aws s3 ls --endpoint-url http://bucket.vpce-0123456789abcdef0-sample.s3.ap-northeast-1.vpce.amazonaws.com
2024-08-13 04:10:06 test-bucket-blog
アクセスができることを確認しました。
補足(IAMポリシーの評価論理)
Condition 句内の、条件演算子(本記事では NotIpAddress)内に複数の条件コンテキストキー(本記事では、aws:SourceIp と aws:VpcSourceIp)がある場合、コンテキストキーは論理 AND を使用して評価されます。
この場合、パブリック IP アドレス 35.78.2.29/32 と プライベート IP アドレス 172.31.0.0/16 のどちらの値も一致しない場合、Deny されるという意味合いでの AND 評価となります。
参考資料
[1] インターフェイスVPCエンドポイント AWS サービス を使用して にアクセスする - Amazon Virtual Private Cloud
[2] Amazon S3 バケットアクセスを特定の IP または VPC に制限する | AWS re:Post
[3] 複数のコンテキストキーまたは値による条件 - AWS Identity and Access Management